package com.leoman.service.impl;

import com.leoman.controller.weixin.WeixinBaseController;
import com.leoman.core.Configue;
import com.leoman.core.Constant;
import com.leoman.dao.AreaDao;
import com.leoman.dao.ImageDao;
import com.leoman.dao.QuestionDao;
import com.leoman.dao.TypeDao;
import com.leoman.entity.Area;
import com.leoman.entity.Image;
import com.leoman.entity.Question;
import com.leoman.entity.Type;
import com.leoman.entity.vo.QuestionVo;
import com.leoman.entity.vo.WxContactVo;
import com.leoman.entity.vo.WxUserVo;
import com.leoman.service.QuestionService;
import com.leoman.utils.DateUtils;
import com.leoman.utils.MessageTimerWork;
import com.leoman.utils.ReadExcelUtil;
import com.leoman.utils.SendMsgWork;
import me.chanjar.weixin.cp.bean.WxCpUser;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartRequest;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * 反馈问题
 * Created by 涂奕恒 on 2016/3/8.
 */
@Service
public class QuestionServiceImpl implements QuestionService {

    @Autowired
    private QuestionDao questionDao;

    @Autowired
    private ImageDao imageDao;

    @Autowired
    private TypeDao typeDao;

    @Autowired
    private AreaDao areaDao;

    @Override
    public List<Question> findAll() {
        return questionDao.findList();
    }

    @Override
    public Page<Question> find(Integer pageNum, Integer pageSize) {
        return questionDao.findList(new PageRequest(pageNum - 1, pageSize));
    }

    @Override
    public Page<Question> find(Integer pageNum) {
        return questionDao.findList(new PageRequest(pageNum - 1, Constant.PAGE_DEF_SIZE));
    }

    @Override
    public Question getById(Integer id) {
        return questionDao.findOne(id);
    }

    @Override
    public Question deleteById(Integer id) {
        Question question = questionDao.findOne(id);
        question.setIsCut(Constant.IS_CUT_YES);
        questionDao.save(question);
        return null;
    }

    @Override
    public Question create(Question question) {
        return questionDao.save(question);
    }

    @Override
    public Question update(Question question) {
        return questionDao.save(question);
    }

    @Override
    @Transactional
    public void deleteAll(Integer[] ids) {
        for (Integer id : ids) {
            deleteById(id);
        }
    }

    @Override
    public List<Map<String, Object>> pageToExcel(Map<String, Object> map) {
        List<Map<String, Object>> list = new ArrayList<>();
        Map<String, Object> params;
        List<Question> baseList;

        if (StringUtils.isBlank(map.get("typeId").toString())) {
            baseList = questionDao.findList();
        } else {
            if (map.get("typeId").toString().equals("1")) {
                // 安全问题
                baseList = questionDao.findListNotByTypeName("%6S%");
            } else {
                // 6S问题
                baseList = questionDao.findListByTypeName("%6S%");
            }
        }

        List<Image> imageList;
        StringBuffer sb = new StringBuffer("");

        Set set;
        Iterator iterator;
        Map.Entry tempMap;

        if (baseList != null) {
            for (Question question : baseList) {
                params = new HashMap<>();
                params.put("id", question.getId());
                params.put("type", null != question.getType() ? question.getType().getName() : "");
                params.put("recordDate", question.getRecordDate());
                params.put("area", null != question.getArea() ? question.getArea().getName() : "");
                params.put("descriptionOne", question.getDescriptionOne());
                imageList = imageDao.findListByQuestionId(question.getId());
                for (Image image : imageList) {
                    sb.append(Configue.getServerUrl() + image.getUrl() + "&&&");
                }
                params.put("images", sb.toString().length() > 0 ? (sb.toString().substring(0, sb.toString().length() - 3)) : "");
                params.put("descriptionTwo", question.getDescriptionTwo());
                params.put("scoreOne", null == question.getScoreOne() ? 0 : question.getScoreOne());
                params.put("scoreTwo", null == question.getScoreTwo() ? 0 : question.getScoreTwo());
                params.put("scoreThree", null == question.getScoreThree() ? 0 : question.getScoreThree());
                params.put("scoreFour", null == question.getScoreFour() ? 0 : question.getScoreFour());
                params.put("scoreFive", null == question.getScoreFive() ? 0 : question.getScoreFive());
                params.put("scoreSix", null == question.getScoreSix() ? 0 : question.getScoreSix());
                params.put("scoreSeven", null == question.getScoreSeven() ? 0 : question.getScoreSeven());
                params.put("nameOne", question.getNameOne());
                params.put("sectionOne", question.getSectionOne());
                params.put("descriptionThree", question.getDescriptionThree());
                params.put("scoreEight", null == question.getScoreEight() ? 0 : question.getScoreEight());
                params.put("scoreNine", null == question.getScoreNine() ? 0 : question.getScoreNine());
                params.put("scoreTen", null == question.getScoreTen() ? 0 : question.getScoreTen());
                params.put("nameTwo", question.getNameTwo());
                params.put("sectionTwo", question.getSectionTwo());
                params.put("planDateOne", question.getPlanDateOne());
                params.put("actualDateOne", question.getActualDateOne());
                params.put("descriptionFour", question.getDescriptionFour());
                params.put("scoreEleven", null == question.getScoreEleven() ? 0 : question.getScoreEleven());
                params.put("scoreTwelve", null == question.getScoreTwelve() ? 0 : question.getScoreTwelve());
                params.put("scoreThirteen", null == question.getScoreThirteen() ? 0 : question.getScoreThirteen());
                params.put("nameThree", question.getNameThree());
                params.put("sectionThree", question.getSectionThree());
                params.put("planDateTwo", question.getPlanDateTwo());
                params.put("actualDateTwo", question.getActualDateTwo());
                params.put("isCut", question.getIsCut() == 0 ? "未删除" : "已删除");
                switch (question.getStatus()) {
                    case 0:
                        params.put("status", "未执行");
                        break;
                    case 1:
                        params.put("status", "正在执行");
                        break;
                    case 2:
                        params.put("status", "已关闭");
                        break;
                }

                // 去掉null值
                set = params.entrySet();
                iterator = set.iterator();
                while (iterator.hasNext()) {
                    tempMap = (Map.Entry) iterator.next();
                    params.put(tempMap.getKey().toString(), null == tempMap.getValue() ? "" : tempMap.getValue());
                }

                list.add(params);
                sb = new StringBuffer("");
            }
        }

        return list;
    }

    @Override
    @Transactional
    public Integer sendInfo(Integer questionId, String section, String name, String sectionId, String userId) {
        try {
            Question question = questionDao.findOne(questionId);

            question.setNameTwo(name);
            question.setSectionTwo(section);
            question.setStatus(Constant.STATUS_001);

            // 保存反馈问题状态信息
            questionDao.save(question);

            // 调用线程发送微信消息
            new MessageTimerWork(sectionId, userId, question);

            return 1;
        } catch (Exception e) {
            e.printStackTrace();

            return 0;
        }
    }

    @Override
    @Transactional
    public Integer readExcelInfo(MultipartRequest multipartRequest) {
        Question question;
        String[] imageString;
        Image tempImage;

        try {
            // 获取上传的反馈问题文件
            // 读取excel
            // 写入数据库
            MultipartFile multipartFile = multipartRequest.getFile("feedback");

            List<QuestionVo> list = ReadExcelUtil.readExcel(multipartFile);

            if (null == list || list.size() == 0) {
                return 0;
            }

            Type tempType;
            Area tempArea;

            for (QuestionVo questionVo : list) {
                if (null == questionVo.getId()) {
                    question = new Question();
                } else {
                    question = questionDao.findOne(questionVo.getId());
                }

                if (null == question) {
                    question = new Question();
                }

                tempType = typeDao.findListByName(questionVo.getType()).get(0);
                tempArea = areaDao.findListByName(questionVo.getArea()).get(0);

                question.setType(tempType);
                question.setArea(tempArea);
                question.setRecordDate(questionVo.getRecordDate());
                question.setDescriptionOne(questionVo.getDescriptionOne());
                question.setDescriptionTwo(questionVo.getDescriptionTwo());
                question.setScoreOne(questionVo.getScoreOne());
                question.setScoreTwo(questionVo.getScoreTwo());
                question.setScoreThree(questionVo.getScoreThree());
                question.setScoreFour(questionVo.getScoreFour());
                question.setScoreFive(questionVo.getScoreFive());
                question.setScoreSix(questionVo.getScoreSix());
                question.setScoreSeven(questionVo.getScoreSeven());
                question.setNameOne(questionVo.getNameOne());
                question.setSectionOne(questionVo.getSectionOne());
                question.setDescriptionThree(questionVo.getDescriptionThree());
                question.setScoreEight(questionVo.getScoreEight());
                question.setScoreNine(questionVo.getScoreNine());
                question.setScoreTen(questionVo.getScoreTen());
                question.setNameTwo(questionVo.getNameTwo());
                question.setSectionTwo(questionVo.getSectionTwo());
                question.setPlanDateOne(questionVo.getPlanDateOne());
                question.setActualDateOne(questionVo.getActualDateOne());
                question.setDescriptionFour(questionVo.getDescriptionFour());
                question.setScoreEleven(questionVo.getScoreEleven());
                question.setScoreTwelve(questionVo.getScoreTwelve());
                question.setScoreThirteen(questionVo.getScoreThirteen());
                question.setNameThree(questionVo.getNameThree());
                question.setSectionThree(questionVo.getSectionThree());
                question.setPlanDateTwo(questionVo.getPlanDateTwo());
                question.setActualDateTwo(questionVo.getActualDateTwo());
                question.setIsCut(questionVo.getIsCut().equals("未删除") ? 0 : 1);
                if (questionVo.getStatus().equals("未执行")) {
                    question.setStatus(0);
                } else if (questionVo.getStatus().equals("正在执行")) {
                    question.setStatus(1);
                } else {
                    question.setStatus(2);
                }

                questionDao.save(changeScoreByParams(question));

                imageString = questionVo.getImages().split("&&&");

                if (null != question.getId()) {
                    // 先统一清除该反馈问题的图片
                    List<Image> imageList = imageDao.findListByQuestionId(question.getId());
                    for (Image image : imageList) {
                        imageDao.delete(image);
                    }
                }

                String uploadUrl = Configue.getServerUrl();
                for (String str : imageString) {
                    str = str.replace(uploadUrl, "");
                    if (StringUtils.isNotEmpty(str)) {
                        tempImage = new Image();
                        tempImage.setUrl(str);
                        tempImage.setQuestion(question);

                        imageDao.save(tempImage);
                    }
                }
            }

            return 1;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    @Override
    @Transactional
    public Integer addQuestion(HttpServletRequest request, Integer areaId, Integer typeId, String memberName, String contactText, String description, Integer userType) {
        String memberOne = "";
        String contactOne = "";

        try {
            Area area = null;
            if (null != areaId) {
                area = new Area();
                area.setId(areaId);
            }
            Type type = typeDao.findOne(typeId);

            // 获取当前用户id
            WxCpUser wxCpUser = (WxCpUser) request.getSession().getAttribute(Constant.SESSION_WEIXIN_WXUSER);

            for (WxContactVo wxContactVo : WeixinBaseController.getWxContactList(request)) {
                for (WxUserVo wxUserVo : wxContactVo.getUserList()) {
                    // 找出匹配的用户信息
                    if (wxUserVo.getId().equals(wxCpUser.getUserId())) {
                        memberOne = wxUserVo.getName();
                        contactOne = wxContactVo.getName();
                    }
                }
            }

            Question question = new Question();
            question.setType(type);
            question.setRecordDate(DateUtils.dateToString(new Date(), "yyyy-MM-dd HH:mm:ss"));
            question.setArea(area);
            question.setDescriptionOne(contactText);
            question.setDescriptionTwo(description);
            question.setNameOne(memberOne);
            question.setSectionOne(contactOne);
            question.setNameTwo(memberName);
            question.setSectionTwo(contactText);
            question.setIsCut(0);
            question.setStatus(0);

            questionDao.save(question);

            // 给管理员推送消息
            // 调用线程发送微信消息
            new SendMsgWork(userType, "有新的" + type.getName() + "问题上传");

            return question.getId();
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    @Override
    public Page<Question> findList(Integer pageNum, Integer pageSize) {
        PageRequest pageRequest = new PageRequest(pageNum - 1, pageSize, Sort.Direction.DESC, "id");
        return questionDao.findList(pageRequest);
    }

    @Override
    public Integer updateQuestion(Integer id, Integer type, String recordDate,
                                  Integer areaId, String descriptionOne,
                                  String descriptionTwo, Integer scoreOne,
                                  Integer scoreTwo, Integer scoreThree, Integer scoreFour,
                                  Integer scoreFive, Integer scoreSix, Integer scoreSeven,
                                  String nameOne, String sectionOne, String descriptionThree,
                                  Integer scoreEight, Integer scoreNine, Integer scoreTen,
                                  String nameTwo, String sectionTwo, String planDateOne,
                                  String actualDateOne, Integer isCut, Integer status,
                                  String tempAddImageIds, String tempDelImageIds) {
        try {
            String[] addImageIds = tempAddImageIds.split(",");
            String[] delImageIds = tempDelImageIds.split(",");

            Question question;

            if (null == id || id == 0) {
                question = new Question();
            } else {
                question = questionDao.findOne(id);
            }

            Type type1 = typeDao.findOne(type);

 /*           Area area = new Area();
            area.setId(areaId);
            question.setArea(area);*/
            if(areaId != null && areaId > 0) {
                Area area = new Area();
                area.setId(areaId);
                question.setArea(area);
            } else {
                question.setArea(null);
            }
            question.setType(type1);
            question.setRecordDate(recordDate);
            question.setDescriptionOne(descriptionOne);
            question.setDescriptionTwo(descriptionTwo);
            question.setScoreOne(scoreOne);
            question.setScoreTwo(scoreTwo);
            question.setScoreThree(scoreThree);
            question.setScoreFour(scoreFour);
            question.setScoreFive(scoreFive);
            question.setScoreSix(scoreSix);
            question.setScoreSeven(scoreSeven);
            question.setNameOne(nameOne);
            question.setSectionOne(sectionOne);
            question.setDescriptionThree(descriptionThree);
            question.setScoreEight(scoreEight);
            question.setScoreNine(scoreNine);
            question.setScoreTen(scoreTen);
            question.setNameTwo(nameTwo);
            question.setSectionTwo(sectionTwo);
            question.setPlanDateOne(planDateOne);
            question.setActualDateOne(actualDateOne);
            question.setIsCut((null == id || id == 0) ? Constant.IS_CUT_NO : isCut);
            question.setStatus((null == id || id == 0) ? Constant.STATUS_000 : status);

            questionDao.save(changeScoreByParams(question));

            // 保存反馈问题图片集合
            Image image;
            for (String imageId : addImageIds) {
                if (null != imageId && !imageId.equals("")) {
                    image = imageDao.findOne(Integer.parseInt(imageId));
                    image.setQuestion(question);

                    imageDao.save(image);
                }
            }

            // 删除反馈问题图片
            for (String imageId : delImageIds) {
                if (null != imageId && !imageId.equals("")) {
                    imageDao.delete(Integer.parseInt(imageId));
                }
            }

            return question.getId();
        } catch (NumberFormatException e) {
            e.printStackTrace();
            return 0;
        }
    }

    @Override
    public Page<Question> pageByParam(final Integer typeId, Integer pageNum, Integer pageSize) {
        return questionDao.findAll(new Specification<Question>() {
            @SuppressWarnings("ToArrayCallWithZeroLengthArrayArgument")
            @Override
            public Predicate toPredicate(Root<Question> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                Predicate result = null;
                List<Predicate> predicateList = new ArrayList<>();
                if (null != typeId) {
                    if (typeId == 1) {
                        // 安全问题
                        predicateList.add(cb.notLike(root.get("type").get("name").as(String.class), "%6S%"));
                    } else {
                        // 6S问题
                        predicateList.add(cb.like(root.get("type").get("name").as(String.class), "%6S%"));
                    }
                }

                predicateList.add(cb.equal(root.get("isCut").as(Integer.class), 0));

                if (predicateList.size() > 0) {
                    result = cb.and(predicateList.toArray(new Predicate[]{}));
                }

                if (result != null) {
                    query.where(result);
                }
                return query.getGroupRestriction();
            }

        }, new PageRequest(pageNum - 1, pageSize, Sort.Direction.DESC, "id"));
    }

    // 修改分数
    private Question changeScoreByParams(Question question) {
        // 计算得分（A）=发现区域*专业程度*关键程度*事故可能性+法规要求
        // 实际得分（B）根据计算得分的区间确定：
        // ⑴A≥81，B=5;        ⑵81＞A≥55，B=4；
        // ⑶ 55＞A≥28，B=3；  ⑷ 28＞A≥8，B=2；   ⑸ 8＞A≥1，B=1。

        // 临时措施计算得分（C）=
        // 临时措施判别得分*实际得分（B）
        // 临时措施实际得分（D）根据临时措施计算得分（C）的区间确定：
        // ⑴C≥13，D=5;        ⑵13＞C≥10，D=4；
        // ⑶ 10＞C≥7，D=3；  ⑷ 7＞C≥4，D=2；   ⑸ 4＞C≥1，D=1。

        if ((question.getType().getName().equals("安全隐患") || question.getType().getName().equals("安全改善及亮点") || question.getType().getName().equals("安全隐患整改反馈"))
                && null != question.getScoreOne() && 0 != question.getScoreOne()
                && null != question.getScoreTwo() && 0 != question.getScoreTwo()
                && null != question.getScoreThree() && 0 != question.getScoreThree()
                && null != question.getScoreFour() && 0 != question.getScoreFour()) {
            question.setScoreSix(question.getScoreOne() * question.getScoreTwo() * question.getScoreThree() * question.getScoreFour() + question.getScoreFive());
            if (null == question.getScoreSix() || question.getScoreSix() < 1) {
                question.setScoreSeven(0);
            } else if (1 <= question.getScoreSix() && question.getScoreSix() < 8) {
                question.setScoreSeven(1);
            } else if (8 <= question.getScoreSix() && question.getScoreSix() < 28) {
                question.setScoreSeven(2);
            } else if (28 <= question.getScoreSix() && question.getScoreSix() < 55) {
                question.setScoreSeven(3);
            } else if (55 <= question.getScoreSix() && question.getScoreSix() < 81) {
                question.setScoreSeven(4);
            } else {
                question.setScoreSeven(5);
            }

            if (null != question.getScoreEight() && 0 != question.getScoreEight()) {
                question.setScoreNine(question.getScoreEight() * question.getScoreSeven());
            }
            if (null == question.getScoreNine() || question.getScoreNine() < 1) {
                question.setScoreTen(0);
            } else if (1 <= question.getScoreNine() && question.getScoreNine() < 4) {
                question.setScoreTen(1);
            } else if (4 <= question.getScoreNine() && question.getScoreNine() < 7) {
                question.setScoreTen(2);
            } else if (7 <= question.getScoreNine() && question.getScoreNine() < 10) {
                question.setScoreTen(3);
            } else if (10 <= question.getScoreNine() && question.getScoreNine() < 13) {
                question.setScoreTen(4);
            } else {
                question.setScoreTen(5);
            }
        }

        return question;
    }
}
